package com.flectothink.wch;

import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.DATA_CHANNEL_CHARACTERISTIC_CONFIG;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.NOTIFY_CHARACTERISTIC;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.NOTIFY_WRITE_CHARACTERISTIC;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.UUID_NOTIFY_CHARACTERISTIC;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.eventAppUpgrade;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.eventBleCentralState;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.eventBluetooth;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.eventConnectAIO;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.eventConnectStatus;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.eventDisConnectAIO;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.eventDownloading;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.eventOpenPermission;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.eventScanAIO;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.eventStopScanAIO;
import static flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService.eventWifi;

import android.Manifest;
import android.annotation.SuppressLint;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCallback;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattDescriptor;
import android.bluetooth.BluetoothGattService;
import android.bluetooth.BluetoothManager;
import android.bluetooth.BluetoothProfile;
import android.bluetooth.le.BluetoothLeScanner;
import android.bluetooth.le.ScanCallback;
import android.bluetooth.le.ScanFilter;
import android.bluetooth.le.ScanResult;
import android.bluetooth.le.ScanSettings;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.net.NetworkCapabilities;
import android.net.NetworkRequest;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelUuid;
import android.text.TextUtils;
import android.util.Log;
import android.view.View;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

import com.flectothink.wch.helper.AIOHelper;
import flexolink.sdk.core.bleDeviceSdk.sdklib.ble.BleEEGService;
import io.flutter.embedding.android.FlutterActivity;
import io.flutter.embedding.engine.FlutterEngine;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugins.GeneratedPluginRegistrant;

public class MainActivity extends FlutterActivity {
    private final static String TAG = "MainActivity";
    private String[] permission = new String[]{   Manifest.permission.ACCESS_FINE_LOCATION,
            Manifest.permission.ACCESS_COARSE_LOCATION};
    public static final int REQUEST_ENABLE_BT = 100;
    private EventChannel.EventSink bleEventSink = null;
    private AIOHelper aioHelper = null;

    ///去重判断
    private byte[] repeatFlag;
    private long lastTimemillis;

    ///蓝牙中心状态
    private int centralIsOpen = -1;

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == 1) {
                MainActivity.this.aioHelper.methodChannel.invokeMethod(eventConnectStatus, msg.obj);
            } else if (msg.what == 2){
                MainActivity.this.aioMethodChannel.invokeMethod(eventBluetooth, msg.obj);
            } else if (msg.what == 5) {
                Map<Object, Object> data = new HashMap<>();
                data.put("wifiName", msg.obj);
                aioMethodChannel.invokeMethod(eventWifi, data);
            }
        }
    };

    MethodChannel aioMethodChannel = null;

    @Override
    protected void onPause() {
        super.onPause();
    }

    @Override
    protected void onResume() {
        super.onResume();
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mBluetoothStateReceiver);
    }

    private final BroadcastReceiver mBluetoothStateReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            final String action = intent.getAction();

            if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
                final int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR);

                Map<String, Object> central = new HashMap<String, Object>();

                switch (state) {
                    case BluetoothAdapter.STATE_OFF:
                        Log.d("蓝牙", "关闭");
                        // 蓝牙已关闭
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                central.put("isOpen", false);
                                aioMethodChannel.invokeMethod(eventBleCentralState, central);
                                centralIsOpen = 0;
                            }
                        });

                        break;
                    case BluetoothAdapter.STATE_TURNING_OFF:
                        // 蓝牙正在关闭
                        break;
                    case BluetoothAdapter.STATE_ON:
                        Log.d("蓝牙", "开启");
                        // 蓝牙已打开
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                Log.d("蓝牙", "runOnUiThread");
                                central.put("isOpen", true);
                                aioMethodChannel.invokeMethod(eventBleCentralState, central);
                                centralIsOpen = 1;
                            }
                        });
                        break;
                    case BluetoothAdapter.STATE_TURNING_ON:
                        // 蓝牙正在打开
                        break;
                }
            }
        }
    };

    @Override
    public void configureFlutterEngine(FlutterEngine flutterEngine) {
        IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
        registerReceiver(mBluetoothStateReceiver, filter);

        NetworkRequest request =
                new NetworkRequest.Builder()
                        .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
                        .build();

        GeneratedPluginRegistrant.registerWith(flutterEngine);
        BluetoothManager bluetoothManager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        BleEEGService.getInstance().setBleAdapter(BluetoothAdapter.getDefaultAdapter());
        centralIsOpen = BleEEGService.getInstance().getBleAdapter().isEnabled() ? 1 : 0;

        aioHelper = new AIOHelper(getActivity());

        EventChannel aioChannel = new EventChannel(flutterEngine.getDartExecutor(), "com.flexolink.wch/aio");

        aioChannel.setStreamHandler(aioHelper);

        aioMethodChannel = new MethodChannel(flutterEngine.getDartExecutor(), "com.flexolink.wch/aio/scan");
        aioMethodChannel.setMethodCallHandler(new MethodChannel.MethodCallHandler() {
            @SuppressLint("MissingPermission")
            @Override
            public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
//                Log.d(TAG, "原生接收到：" + call.method);
//                Log.d(TAG, "原生接收到：" + call.arguments);

                if (call.method.equals(eventOpenPermission)) {
                    initPermmision();
                } else if (call.method.equals(eventBluetooth)) {
                    ArrayList<Integer> list = (ArrayList<Integer>) call.arguments;
                    byte[] bytes = new byte[list.size()];
                    for (int i = 0; i < list.size(); i ++) {
                        bytes[i] = list.get(i).byteValue();
                    }
                    BleEEGService.getInstance().writeData(bytes);
                    Log.d(TAG, "发送指令给一体机");
                } else if (call.method.equals(eventScanAIO)) {
                    startBle();
                } else if (call.method.equals(eventConnectAIO)) {
                    Map<String, String> map = (Map<String, String>) call.arguments;
                    String deviceName = map.get("deviceName");
                    String mac = map.get("mac");
                    MainActivity.this.connect(BleEEGService.getInstance().getBleAdapter(), mac, deviceName);
                } else if (call.method.equals(eventDisConnectAIO)) {
                    aioHelper.getGatt().disconnect();
                } else if (call.method.equals(eventAppUpgrade)) {
                    Map<String, String> map = (Map<String, String>) call.arguments;
                    String apkUrl = map.get("apkUrl");
                    String apkName = map.get("apkName");
//                    MainActivity.this.downloading(apkUrl, apkName);
                } else if (call.method.equals(eventWifi)) {
                    getWifiName();
                } else if (call.method.equals(eventStopScanAIO)) {
                    BluetoothLeScanner scanner = BleEEGService.getInstance().getBleAdapter().getBluetoothLeScanner();
                    scanner.stopScan(scanCallback);
                    aioHelper.clearDevice();
                } else if (call.method.equals(eventBleCentralState)) {
                    runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            Map<String, Object> state = new HashMap<String, Object>();
                            state.put("BLECentralStatus", centralIsOpen);
                            aioMethodChannel.invokeMethod(eventBleCentralState, state);
                        }
                    });
                }
            }
        });

        aioHelper.methodChannel = aioMethodChannel;

    }

    private void initPermmision(){
        List<String> mPermissionList = new ArrayList<>();
        // Android 版本大于等于 12 时，申请新的蓝牙权限
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            mPermissionList.add(Manifest.permission.BLUETOOTH_SCAN);
            mPermissionList.add(Manifest.permission.BLUETOOTH_ADVERTISE);
            mPermissionList.add(Manifest.permission.BLUETOOTH_CONNECT);
        } else {
            mPermissionList.add(Manifest.permission.BLUETOOTH);
        }

        mPermissionList.add(Manifest.permission.WRITE_EXTERNAL_STORAGE);
        mPermissionList.add(Manifest.permission.READ_EXTERNAL_STORAGE);

        if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED) {
            mPermissionList.add(Manifest.permission.ACCESS_FINE_LOCATION);
        } else {
            if (!BleEEGService.getInstance().getBleAdapter().isEnabled()) {
                Intent enableBtIntent = new Intent(
                        BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            }
        }

        ActivityCompat.requestPermissions(MainActivity.this, mPermissionList.toArray(new String[0]), 101);
    }

    @SuppressLint("MissingPermission")
    private void startBle() {
        BluetoothManager manager = (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        BleEEGService.getInstance().setBleAdapter(manager.getAdapter());
        BleEEGService.getInstance().setmScanner(BleEEGService.getInstance().getBleAdapter().getBluetoothLeScanner());
        List<ScanFilter> filters = new ArrayList<ScanFilter>();
//        filters.add(0, new ScanFilter.Builder().setDeviceName("FLEX_AIO").build());
        ParcelUuid mServiceUuidFilter = ParcelUuid.fromString(NOTIFY_CHARACTERISTIC);
        filters.add(0, new ScanFilter.Builder().setServiceUuid(mServiceUuidFilter).build());
        ScanSettings settings = new ScanSettings.Builder().setScanMode(ScanSettings.SCAN_MODE_LOW_LATENCY).build();
        BleEEGService.getInstance().getmScanner().startScan(scanCallback);
    }



    ScanCallback scanCallback = new ScanCallback() {
        @SuppressLint("MissingPermission")
        @Override
        public void onScanResult(int callbackType, ScanResult result) {
            super.onScanResult(callbackType, result);
            BleEEGService.getInstance().setDevice( result.getDevice());
            if (BleEEGService.getInstance().getDevice().getName() != null) {
                BluetoothDevice device = result.getDevice();
//                Log.d(TAG, device.getName());
                MainActivity.this.aioHelper.addDevice(device);

            }
        }
    };

    private final BluetoothGattCallback mGattCallback = new BluetoothGattCallback() {
        @SuppressLint("MissingPermission")
        @Override
        public void onMtuChanged(BluetoothGatt gatt, int mtu, int status) {
            super.onMtuChanged(gatt, mtu, status);
            if (BluetoothGatt.GATT_SUCCESS == status) {
                Log.i(TAG, "Attempting to start service discovery:" + BleEEGService.getInstance().getmBluetoothGatt().discoverServices());
            } else {
                Log.i(TAG, "设置MTU失败");

            }
        }

        @SuppressLint("MissingPermission")
        @Override
        public void onConnectionStateChange(BluetoothGatt gatt, int status, int newState) {

            MainActivity.this.aioHelper.setGatt(BleEEGService.getInstance().getmBluetoothGatt());

            if (newState == BluetoothProfile.STATE_CONNECTED) {
//                mBluetoothGatt = gatt;
                BluetoothDevice device = BleEEGService.getInstance().getmBluetoothGatt().getDevice();

                String mac = device.getAddress();
                BleEEGService.getInstance().getmBluetoothGatt().requestConnectionPriority(BluetoothGatt.CONNECTION_PRIORITY_HIGH);
                BleEEGService.getInstance().getmBluetoothGatt().requestMtu(512);

                Map<Object, Object> map = new HashMap<>();
                map.put("deviceName", device.getName());
                map.put("mac", device.getAddress());
                map.put("isConnected", true);
                map.put("channelName", "scan");
                map.put("code", 101);

                Message msg = new Message();
                msg.obj = map;
                msg.what = 1;
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        handler.sendMessage(msg);
                    }
                }, 1000);

            } else if (newState == BluetoothProfile.STATE_DISCONNECTED) {
                Map<Object, Object> map = new HashMap<>();
                map.put("deviceName", BleEEGService.getInstance().getDevice().getName());
                map.put("mac", BleEEGService.getInstance().getDevice().getAddress());
                map.put("isConnected", false);
                map.put("channelName", "scan");
                map.put("code", 101);

                Message msg = new Message();
                msg.obj = map;
                msg.what = 1;
                handler.postDelayed(new Runnable() {
                    @Override
                    public void run() {
                        handler.sendMessage(msg);
                    }
                }, 1000);

                BleEEGService.getInstance().getmBluetoothGatt().close();
                BleEEGService.getInstance().setmBluetoothGatt(null);
            }
        }

        @Override
        public void onServicesDiscovered(BluetoothGatt gatt, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                displayGattServices(getSupportedGattServices());
                //打开通知
                if (BleEEGService.getInstance().getNotifyGattCharacteristic() != null) {
                    setCharacteristicNotification(BleEEGService.getInstance().getNotifyGattCharacteristic(), true);
                }
            } else {
                Log.d(TAG, "onServicesDiscovered received: " + status);
            }
        }

        @Override
        public void onCharacteristicRead(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            Log.d(TAG, "onCharacteristicRead...");
        }

        @SuppressLint("MissingPermission")
        @Override
        public void onCharacteristicChanged(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic) {
            byte [] value = characteristic.getValue();
            Log.d(TAG, "原生接收到..."+characteristic.getValue());
            ///如果在很短的时间内收到多条一样的数据，则第一条之外的都扔掉
            long timemillis = System.currentTimeMillis();

            if (timemillis - lastTimemillis < 500 && value[5] == repeatFlag[5]) {
                lastTimemillis = timemillis;
                repeatFlag = value;
                return;
            }

            lastTimemillis = timemillis;
            repeatFlag = value;

            Map<Object, Object> map = new HashMap<>();
            map.put("deviceName", gatt.getDevice().getName());
            map.put("cmd", value);

            Message msg = new Message();
            msg.what = 2;
            msg.obj = map;
            handler.postDelayed(new Runnable() {
                @Override
                public void run() {
                    handler.sendMessage(msg);
                }
            }, 100);
        }

        @Override
        public void onCharacteristicWrite(BluetoothGatt gatt, BluetoothGattCharacteristic characteristic, int status) {
            if (status == BluetoothGatt.GATT_SUCCESS) {
                Log.d(TAG, "发送成功");
            }
        }

        @Override
        public void onDescriptorWrite(BluetoothGatt gatt, BluetoothGattDescriptor descriptor, int status) {
        }

        @Override
        public void onReadRemoteRssi(BluetoothGatt gatt, int rssi, int status) {
            super.onReadRemoteRssi(gatt, rssi, status);
            if (status == BluetoothGatt.GATT_SUCCESS) {
            }
        }
    };
    @SuppressLint("MissingPermission")
    private void setCharacteristicNotification(BluetoothGattCharacteristic characteristic, boolean enabled) {
        if (BleEEGService.getInstance().getmBluetoothGatt() == null) {
            Log.w(TAG, "mBluetoothGatt not initialized");
            return;
        }
        BleEEGService.getInstance().getmBluetoothGatt().setCharacteristicNotification(characteristic, enabled);
        // This is specific to Heart Rate Measurement.
        if (UUID_NOTIFY_CHARACTERISTIC.equals(characteristic.getUuid())) {
            BluetoothGattDescriptor descriptor = characteristic.getDescriptor(UUID.fromString(DATA_CHANNEL_CHARACTERISTIC_CONFIG));
            if (descriptor != null) {
                descriptor.setValue(BluetoothGattDescriptor.ENABLE_NOTIFICATION_VALUE);
                BleEEGService.getInstance().getmBluetoothGatt().writeDescriptor(descriptor);
            }
        }
        Log.d(TAG, "setCharacteristicNotification...");
    }

    private List<BluetoothGattService> getSupportedGattServices() {
        if (BleEEGService.getInstance().getmBluetoothGatt() == null) return null;

        return BleEEGService.getInstance().getmBluetoothGatt().getServices();
    }



    private void displayGattServices(List<BluetoothGattService> gattServices) {
        if (gattServices == null) return;
        String uuid = null;

        // Loops through available GATT Services.
        for (BluetoothGattService gattService : gattServices) {
            List<BluetoothGattCharacteristic> gattCharacteristics =
                    gattService.getCharacteristics();
            ArrayList<BluetoothGattCharacteristic> charas =
                    new ArrayList<BluetoothGattCharacteristic>();

            // Loops through available Characteristics.
            for (BluetoothGattCharacteristic gattCharacteristic : gattCharacteristics) {
                charas.add(gattCharacteristic);

                uuid = gattCharacteristic.getUuid().toString();
                if (NOTIFY_CHARACTERISTIC.equals(uuid)) {
                    BleEEGService.getInstance().setNotifyGattCharacteristic(gattCharacteristic);
                    MainActivity.this.aioHelper.setReadCharacteristic(gattCharacteristic);
                }
                if (NOTIFY_WRITE_CHARACTERISTIC.equals(uuid)) {
                    BleEEGService.getInstance().setNotifyWriteGattCharacteristic(gattCharacteristic);
                    MainActivity.this.aioHelper.setWriteCharacteristic(gattCharacteristic);
                }

            }
        }

        Log.d(TAG, "displayGattServices...");
    }

    @SuppressLint("MissingPermission")
    public boolean connect(BluetoothAdapter bluetoothAdapter, final String address, String deviceName) {
        Log.d("--connect--", "-connect-");
        if (bluetoothAdapter == null || address == null || TextUtils.isEmpty(deviceName)) {
            Log.w(TAG, "BluetoothAdapter not initialized or unspecified address.");
            return false;
        }
        BluetoothDevice device = null;
        try {
            device = BleEEGService.getInstance().getBleAdapter().getRemoteDevice(address);
        } catch (IllegalArgumentException exception) {
            Log.w(TAG, "Device not found with provided address.");
            return false;
        }
        if (device == null) {
            Log.w(TAG, "Device not found.  Unable to connect.");
            return false;
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
            BleEEGService.getInstance().setmBluetoothGatt(device.connectGatt(this, false, mGattCallback, BluetoothDevice.TRANSPORT_LE));
        }else {
            BleEEGService.getInstance().setmBluetoothGatt(device.connectGatt(this, false, mGattCallback));
        }
        Log.d(TAG, "Trying to create a new connection.");
        return true;
    }

    @SuppressLint("MissingPermission")
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if (resultCode == RESULT_OK && requestCode == REQUEST_ENABLE_BT) {
            Toast.makeText(this, "蓝牙已开启", Toast.LENGTH_SHORT);
        } else if (resultCode == RESULT_OK && requestCode == 101) {
            if (!BleEEGService.getInstance().getBleAdapter().isEnabled()) {
                Intent enableBtIntent = new Intent(
                        BluetoothAdapter.ACTION_REQUEST_ENABLE);
                startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
            }
        }
    }

    private String getConnectWifiSsid(Context context) {

        WifiManager wifiManager = (WifiManager) getSystemService(WIFI_SERVICE);
        WifiInfo wifiInfo = wifiManager.getConnectionInfo();
//        Log.d("wifiInfo------", wifiInfo.toString());
//        Log.d("SSID------", wifiInfo.getSSID());
        String wifi = wifiInfo.getSSID();
        if (wifi.contains("\"")) {
            wifi = wifi.substring(1, wifi.length() - 1);
        }
        if (wifi.contains("unknown")) {
            wifi = "empty";//约定 empty 为 wifi 空的名字
        }
        return wifi;
    }

    private void getWifiName() {
        Message message = new Message();
        message.what=5;
        message.obj = getConnectWifiSsid(MainActivity.this.getContext());
        handler.sendMessage(message);
    }

}